
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <set>

using namespace std;

#include "def.h"
#include "BiContainer.h"
#include "Mutex.h"
#include "Cond.h"
#include "Lockable.h"
#include "VarCol.h"

void VarCol::set (const string& table_name, const string& col_name) {
 dataName = table_name + ".";
 dataName += col_name + ".dat";
}

bool VarCol::open (fstream& data) {
 data.clear ();
 
 try {
  data.open ( dataName.c_str(), fstream::in | fstream::out );
 }
 catch (...) {
  return false;
 }

 return true;
}

bool VarCol::get (fstream& data, int position, string& store) {
 int curLen;

 data.clear();
 data.seekg ( position ); 
 
 if ( data.eof() ) {
  data.clear ();
  data.seekg (-1, ios_base::cur);
  return false;
 }

 attachReader ();

 data >> curLen;
 data.seekg (VARCOL_LENGTH_LENGTH - data.tellg() + position, ios_base::cur);

 if ( data.eof() ) {
  data.clear ();
  data.seekg (-1, ios_base::cur);
  return false;
 }

 store.resize ( curLen );
 data.read (&store[0], curLen);

 detachReader ();

 if ( data.eof() ) {
  data.clear ();
  data.seekg (-1, ios_base::cur);
 }

 return true;
}	

int VarCol::put (fstream& data, int position, string& store) {
 int curLen;
 int retPos;

 if (position != -1) { /* -1 means insert row at end of varcol file */
  data.clear();
  data.seekg ( position ); 

  attachReader ();
 
  data >> curLen;

  detachReader ();
 }

 data.fill ('\0');
 data.flags(ios::left);

 if (curLen >= store.size() && position != -1) { /* we don't have to relocate except if we are
                                                    inserting at end */
  data.seekp ( position + VARCOL_LENGTH_LENGTH);

  writeLock (position);

  data.width ( curLen );
  data << store;

  writeUnlock (position);

  return position;
 }
 else { /* relocate to the end of the file */
  data.seekp (0, ios_base::end);

  retPos = data.tellp ();

  writeLock (position); /* locking -1 stands for locking appending to end of file */

  data.width ( VARCOL_LENGTH_LENGTH );
  data << store.size();
  
  data.width ( store.size() );
  data << store;

  writeUnlock (position);

  return retPos;
 }
}
